import xlrd
from xlrd.sheet import Sheet
from xlrd.book import Book
from Elements import Element
from Enums import PayloadType
from Enums import ServiceType
from Enums import Direction

from Configs import SHEET_ROW_START
from Configs import SHEET_INDEX_NORMAL
from Configs import SHEET_INDEX_TIMESYNC
from Configs import SHEET_INDEX_AVAS
from Configs import SHEET_INDEX_HOSTINFO
from Configs import SHEET_INDEX_POWER
from Configs import SHEET_INDEX_STRUCT
from Configs import SHEET_INDEX_TEXTTABLE
from Configs import SHEET_INDEX_EXTRA

from Configs import WORK_BOOK_PATH
from Configs import COL_INDEX_NAME
from Configs import COL_INDEX_MODULE
from Configs import COL_INDEX_DIRECTION
from Configs import COL_INDEX_SERVICE_TYPE
from Configs import COL_INDEX_OP_TYPE
from Configs import COL_INDEX_OP_CODE
from Configs import COL_INDEX_PAYLOAD_TYPE
from Configs import COL_INDEX_PAYLOAD_STR
from Configs import COL_INDEX_DSC
from Configs import COL_INDEX_PACKAGE
from Configs import COL_INDEX_SWRS_SIGNAL

from Configs import EXTRA_KEY_PULL
from Configs import EXTRA_KEY_SDB


# ==================================================================================

def sheetRow2Element(sheet: Sheet,
                     row: int):
    element = Element()
    name = str(sheet.cell_value(row, COL_INDEX_NAME))
    module = str(sheet.cell_value(row, COL_INDEX_MODULE))
    direction = str(sheet.cell_value(row, COL_INDEX_DIRECTION))
    serviceType = str(sheet.cell_value(row, COL_INDEX_SERVICE_TYPE))
    opType = str(sheet.cell_value(row, COL_INDEX_OP_TYPE))
    opCode = str(sheet.cell_value(row, COL_INDEX_OP_CODE))
    payloadType = str(sheet.cell_value(row, COL_INDEX_PAYLOAD_TYPE))
    payloadStr = str(sheet.cell_value(row, COL_INDEX_PAYLOAD_STR))
    description = str(sheet.cell_value(row, COL_INDEX_DSC))
    package = str(sheet.cell_value(row, COL_INDEX_PACKAGE))
    swrsName = str(sheet.cell_value(row, COL_INDEX_SWRS_SIGNAL))
    # 结构体单元格可能是合并的，需要往上找
    if payloadType == PayloadType.struct.name and len(payloadStr) == 0:
        for r in range(row, 1, -1):
            payloadStr = str(sheet.cell_value(r, COL_INDEX_PAYLOAD_STR))
            if len(payloadStr) != 0:
                break
    element.setSheetName(sheet.name)
    element.setName(name)
    element.setModule(module)
    element.setDirection(direction)
    element.setServiceType(serviceType)
    element.setOpType(opType)
    element.setOpCode(opCode)
    element.setPayloadType(payloadType)
    element.setPayloadStr(payloadStr)
    element.setDescription(description)
    element.setPackage(package)
    element.setSWRSName(swrsName)
    return element


# ==================================================================================
def readBook():
    return xlrd.open_workbook(WORK_BOOK_PATH)


def readNormalSheet(book: Book):
    return book.sheet_by_index(SHEET_INDEX_NORMAL)


def readTimeSyncSheet(book: Book):
    return book.sheet_by_index(SHEET_INDEX_TIMESYNC)


def readAVASSheet(book: Book):
    return book.sheet_by_index(SHEET_INDEX_AVAS)

def readHostInfoSheet(book: Book):
    return book.sheet_by_index(SHEET_INDEX_HOSTINFO)

def readPowerSheet(book: Book):
    return book.sheet_by_index(SHEET_INDEX_POWER)


def readStructSheet(book: Book):
    return book.sheet_by_index(SHEET_INDEX_STRUCT)


def readTextTableSheet(book: Book):
    return book.sheet_by_index(SHEET_INDEX_TEXTTABLE)


def readExtraSheet(book: Book):
    return book.sheet_by_index(SHEET_INDEX_EXTRA)


def readSheetTX(sheet: Sheet):
    list: Element = []
    add = False
    for row in range(SHEET_ROW_START, sheet.nrows):
        element = sheetRow2Element(sheet, row)
        if element.mDirection == Direction.AP_2_CP:
            add = True
            list.append(element)
        else:  # TX和RX是顺序排序
            if add:
                break

    return list


def readSheetRX(sheet: Sheet):
    list: Element = []
    add = False
    for row in range(SHEET_ROW_START, sheet.nrows):
        element = sheetRow2Element(sheet, row)
        if element.mDirection == Direction.CP_2_AP:
            list.append(element)
            add = True
        else:  # TX和RX是顺序排序
            if add:
                break
    return list


def readStructContent(sheet: Sheet):
    list: Element = []
    structNameLast = ""
    for row in range(SHEET_ROW_START, sheet.nrows):
        element = Element()
        structName = str(sheet.cell_value(row, 0))
        memberMix = str(sheet.cell_value(row, 1)).split("_t m")
        textTable = str(sheet.cell_value(row, 2))
        desc = str(sheet.cell_value(row, 3))
        # 合并的单元格没值
        if len(structName) == 0:
            structName = structNameLast
        # 使用前一个的结构体名
        structNameLast = structName
        # ....
        element.setName(structName + "." + memberMix[1])
        element.setPayloadType(memberMix[0])
        element.setPayloadStr(textTable)
        element.setDescription(desc)
        list.append(element)
    return list


def readTexttableContent(sheet: Sheet):
    list: Element = []
    for row in range(SHEET_ROW_START, sheet.nrows):
        element = Element()
        textName = str(sheet.cell_value(row, 0))
        keyValueMix = str(sheet.cell_value(row, 1)).split(" = ")
        desc = str(sheet.cell_value(row, 2))
        element.setName(textName + "." + keyValueMix[1])
        element.setPayloadStr(keyValueMix[0])
        element.setDescription(desc)
        list.append(element)
    return list


def readExtraPull(sheetExtra: Sheet):
    list: Element = []
    for i in range(1, sheetExtra.nrows):
        type = sheetExtra.cell_value(i, 0)
        key = sheetExtra.cell_value(i, 1)
        if type == EXTRA_KEY_PULL:
            element = Element()
            element.setName(type)
            element.setPayloadStr(key)
            list.append(element)
    return list

def readExtraSDB(sheetExtra: Sheet):
    list: Element = []
    for i in range(1, sheetExtra.nrows):
        type = sheetExtra.cell_value(i, 0)
        key = sheetExtra.cell_value(i, 1)
        if type == EXTRA_KEY_SDB:
            element = Element()
            element.setName(type)
            element.setPayloadStr(key)
            list.append(element)
    return list